package com.wzb.mybatisplus.bitaction;

import org.bitcoinj.core.DumpedPrivateKey;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;

import java.math.BigInteger;

public class BitcoinWIFToPublicKey {

    /**
     * 将WIF私钥转换为34个字符的压缩公钥（16进制格式）
     */
    public static String wifToCompressedPublicKeyHex(String wifPrivateKey) {
        try {
            NetworkParameters params = MainNetParams.get();

            // 解析WIF私钥
            DumpedPrivateKey dumpedPrivateKey = DumpedPrivateKey.fromBase58(params, wifPrivateKey);
            ECKey ecKey = dumpedPrivateKey.getKey();

            // 获取压缩公钥（33字节）
            byte[] compressedPublicKey = ecKey.getPubKey();

            // 转换为16进制字符串（66个字符）
            String publicKeyHex = bytesToHex(compressedPublicKey);

            return publicKeyHex;

        } catch (Exception e) {
            throw new IllegalArgumentException("无效的WIF私钥: " + e.getMessage());
        }
    }

    /**
     * 将WIF私钥转换为34个字符的公钥（Base58格式）
     * 注意：标准的压缩公钥是33字节，这里转换为34字符的Base58格式
     */
    public static String wifToCompressedPublicKeyBase58(String wifPrivateKey) {
        try {
            NetworkParameters params = MainNetParams.get();

            // 解析WIF私钥
            DumpedPrivateKey dumpedPrivateKey = DumpedPrivateKey.fromBase58(params, wifPrivateKey);
            ECKey ecKey = dumpedPrivateKey.getKey();

            // 获取压缩公钥（33字节）
            byte[] compressedPublicKey = ecKey.getPubKey();

            // 转换为Base58格式（约34-35个字符）
            String publicKeyBase58 = base58Encode(compressedPublicKey);

            return publicKeyBase58;

        } catch (Exception e) {
            throw new IllegalArgumentException("无效的WIF私钥: " + e.getMessage());
        }
    }

    /**
     * 完整的公钥信息
     */
    public static PublicKeyInfo getPublicKeyInfo(String wifPrivateKey) {
        try {
            NetworkParameters params = MainNetParams.get();
            DumpedPrivateKey dumpedPrivateKey = DumpedPrivateKey.fromBase58(params, wifPrivateKey);
            ECKey ecKey = dumpedPrivateKey.getKey();

            byte[] compressedPublicKey = ecKey.getPubKey();
            byte[] uncompressedPublicKey = ecKey.getPubKeyPoint().getEncoded(false);

            String compressedHex = bytesToHex(compressedPublicKey);
            String uncompressedHex = bytesToHex(uncompressedPublicKey);
            String compressedBase58 = base58Encode(compressedPublicKey);
            String uncompressedBase58 = base58Encode(uncompressedPublicKey);

            return new PublicKeyInfo(
                    wifPrivateKey,
                    compressedHex,
                    uncompressedHex,
                    compressedBase58,
                    uncompressedBase58,
                    compressedPublicKey.length,
                    uncompressedPublicKey.length,
                    compressedBase58.length(),
                    uncompressedBase58.length()
            );

        } catch (Exception e) {
            throw new IllegalArgumentException("无效的WIF私钥: " + e.getMessage());
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * Base58编码
     */
    private static String base58Encode(byte[] input) {
        // Base58字母表
        final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        final BigInteger BASE = BigInteger.valueOf(58);

        // 转换为大整数
        BigInteger num = new BigInteger(1, input);

        // 计算前导零
        int leadingZeros = 0;
        for (byte b : input) {
            if (b == 0) leadingZeros++;
            else break;
        }

        // Base58编码
        StringBuilder result = new StringBuilder();
        while (num.compareTo(BigInteger.ZERO) > 0) {
            BigInteger[] divmod = num.divideAndRemainder(BASE);
            num = divmod[0];
            int digit = divmod[1].intValue();
            result.insert(0, ALPHABET.charAt(digit));
        }

        // 添加前导'1'
        for (int i = 0; i < leadingZeros; i++) {
            result.insert(0, '1');
        }

        return result.toString();
    }

    /**
     * 公钥信息类
     */
    public static class PublicKeyInfo {
        private final String wifPrivateKey;
        private final String compressedPublicKeyHex;
        private final String uncompressedPublicKeyHex;
        private final String compressedPublicKeyBase58;
        private final String uncompressedPublicKeyBase58;
        private final int compressedBytesLength;
        private final int uncompressedBytesLength;
        private final int compressedBase58Length;
        private final int uncompressedBase58Length;

        public PublicKeyInfo(String wifPrivateKey, String compressedPublicKeyHex,
                             String uncompressedPublicKeyHex, String compressedPublicKeyBase58,
                             String uncompressedPublicKeyBase58, int compressedBytesLength,
                             int uncompressedBytesLength, int compressedBase58Length,
                             int uncompressedBase58Length) {
            this.wifPrivateKey = wifPrivateKey;
            this.compressedPublicKeyHex = compressedPublicKeyHex;
            this.uncompressedPublicKeyHex = uncompressedPublicKeyHex;
            this.compressedPublicKeyBase58 = compressedPublicKeyBase58;
            this.uncompressedPublicKeyBase58 = uncompressedPublicKeyBase58;
            this.compressedBytesLength = compressedBytesLength;
            this.uncompressedBytesLength = uncompressedBytesLength;
            this.compressedBase58Length = compressedBase58Length;
            this.uncompressedBase58Length = uncompressedBase58Length;
        }

        // Getters
        public String getWifPrivateKey() { return wifPrivateKey; }
        public String getCompressedPublicKeyHex() { return compressedPublicKeyHex; }
        public String getUncompressedPublicKeyHex() { return uncompressedPublicKeyHex; }
        public String getCompressedPublicKeyBase58() { return compressedPublicKeyBase58; }
        public String getUncompressedPublicKeyBase58() { return uncompressedPublicKeyBase58; }
        public int getCompressedBytesLength() { return compressedBytesLength; }
        public int getUncompressedBytesLength() { return uncompressedBytesLength; }
        public int getCompressedBase58Length() { return compressedBase58Length; }
        public int getUncompressedBase58Length() { return uncompressedBase58Length; }

        @Override
        public String toString() {
            return String.format(
                    "WIF私钥: %s\n\n" +
                            "压缩公钥 (16进制):\n%s\n字节数: %d, 字符数: %d\n\n" +
                            "压缩公钥 (Base58):\n%s\n字符数: %d\n\n" +
                            "非压缩公钥 (16进制):\n%s\n字节数: %d, 字符数: %d\n\n" +
                            "非压缩公钥 (Base58):\n%s\n字符数: %d",
                    wifPrivateKey,
                    compressedPublicKeyHex, compressedBytesLength, compressedPublicKeyHex.length(),
                    compressedPublicKeyBase58, compressedBase58Length,
                    uncompressedPublicKeyHex, uncompressedBytesLength, uncompressedPublicKeyHex.length(),
                    uncompressedPublicKeyBase58, uncompressedBase58Length
            );
        }
    }

}